<?php
/**
 * huhaiqin,2024.10.15
 * 短信逻辑代码，Z视介的版本
 */
namespace Common\Model;
use Think\Model;
class SmsModel extends Model{

    private $smsApiUrl = 'http://192.168.91.86/api/internal/sms/send';
    // 使用的是腾讯的短信通道,短信通道配置
    private $config = [  
        'templateId' => 2070179,  
        'signName' => 'Z视介',
        'phoneNumberSet' => [], //mobile
        'paramsSet' => [] // code
    ];
    
    private $limitTime = 10 * 60; //重发限制时间，默认10分钟

    /**
     * huhaiqin,2024.10.13
     * 生成发送短信的token，利用session = uuid()
     */
    public function create_token($mobile = 1){
        $token = uuid();
        //生成文件
        S($token,$mobile,3600);
        return $token;
    }

    /**
     * huhaiqin,2024.10.13
     * 检测token是否正确
     */
    public function check_token($token = '',$mobile = 1){
        if($token != '' && S($token) == $mobile){
            S($token,NULL); //销毁文件
            return true;
        }
        return false;
    }


    /**
     * huhaiqin,2024.10.11
     * 发送短信
     */
    public function send_sms($mobile = '',$token = '',$type = 'check'){
        // 校验$mobile
        if ($mobile == '') {
            _apiReturn(0, '手机号码不能为空~');
        }
        if (!check_phone($mobile)) {
            _apiReturn(0, '手机号码格式不正确~');
        }

        if(!$this->check_token($token,$mobile)){
            _apiReturn(0,'非法调用~');
        }
        // 检测一下是否需要重发
        $checkResult = $this->_check_has_send($mobile,$type); //前面已经校验了mobile,不可能是 -1
        if($checkResult == 1){
            // 发送验证码
            // 补全短信配置参数
            $code = (string)mt_rand(100000,999999); //生成一个随机数
            //调用私有函数，发送短信
            $checkSend = $this->_send_sms($mobile,$code); 
            if($checkSend['code'] == '200'){
                //表示发送成功，需要往数据库存储数据
                $data = [
                    'mobile'      => $mobile,
                    'code'        => $code,
                    'type'        => $type,
                    'status'      => 1,
                    'is_used'     => 0,
                    'create_time' => time()
                ];
                if($this->add($data)){
                    _apiReturn(1,'success');
                }else{
                    _apiReturn(0,'数据创建失败');
                }
            }else{
                _apiReturn(0,'对不起，短信发送失败');
            }
            return ;
        }
        _apiReturn(0,'验证码已发送，尚未过期~'); 
    }

    /**
     * huhaiqin,2024.10.11
     * 校验验证码，只能校验一次，校验过后就实现
     * return boolean , 以便实现其他业务
     */
    public function check_code($mobile = '',$code = '',$type = 'check'){
        if(!$mobile || !check_phone($mobile)){
            _apiReturn(0,'手机号码格式错误~');
        }
        if($code == ''){
            _apiReturn(0,'验证码不能为空~');
        }
        // 匹配条件
        $map = [
            'mobile'  => $mobile,
            'code'    => $code,
            'is_used' => 0,
            'type'   => $type
        ];
        $check = $this->where($map)->order('id desc')->find(); //确保查出来的是最新的那条数据
        if($check){
            // 检测是否过期
            if((time() - $check['create_time']) <= $this->limitTime){
                //没有过期，表示验证码正确，改数据
                $this->where(['id' => $check['id']])->save(['is_used' => 1]); //标记该短信已被使用
                return 1;
            }else{
                return -1;
            }
        }
        return 0;
    }

    /**
     * huhaiqin,2024.10.11
     * 私有方法，检测是否已经发送过短信
     */
    private function _check_has_send($mobile = '',$type = 'check'){
        //查询条件
        $map = [
            'mobile'  => $mobile,//手机号码
            'type'    => $type,  //验证类型
            'is_used' => 0,      //没被使用过
            'status'  => 1       //短信需要发送成功的
        ];
        $check = $this->where($map)->find();
        if(!$check){
            return 1; //没记录，就是可以发
        }
        //有记录，那么就看看过期了没
        if((time() - $check['create_time']) > $this->limitTime ){
            return 1; //短信已经过期，可以重发
        }
        return 0; //不满足重发条件
    }

    /**
     * huhaiqin，2024.10.11
     * 私有方法，根据给的参数发送短信
     * 改编制杜国俊提供的方法
     */
    private function _send_sms($mobile,$code){
        $this->config['phoneNumberSet'] = [$mobile];
        $this->config['paramsSet'] = [$code];
        // 将数据编码为JSON格式  
        $jsonDataEncoded = json_encode($this->config);  
        // 初始化cURL会话  
        $ch = curl_init($this->smsApiUrl);  
        // 设置cURL选项  
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 将curl_exec()获取的信息以文件流的形式返回，而不是直接输出。  
        curl_setopt($ch, CURLOPT_POST, true); // 启用POST请求  
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonDataEncoded); // 设置POST请求的数据  
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(  
            'Content-Type: application/json', // 设置请求头，表明发送的数据是JSON格式  
            'Content-Length: ' . strlen($jsonDataEncoded) // 设置请求头的Content-Length  
        ));  
        
        // 执行cURL请求并获取响应  
        $response = curl_exec($ch);  
        // 关闭cURL会话  
        curl_close($ch);  
        return json_decode($response,true);
    }

}